package com.archempower.core.tools;

import com.spire.presentation.Presentation;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.util.PPTX2PNG;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;

/**
 * @author yfdai
 */
public class Hello {

  public static void main(String[] args) throws Exception {
    var hello = new Hello();
    hello.outdir = new File("out/");

    if (hello.parseCommandLine(args)) {


      //方法一: 使用poi的工具组件PPTX2PNG
      if (hello.mode == 0) {
        hello.convertPPTX2Image1(hello.filename);
        System.out.println("Done.");
      }

      //方法二
      if (hello.mode == 2) {
        convertPPTX2Image2(hello.filename);
        System.out.println("Done.");
      }

      //方法三: 使用spire.presentation组件
      if (hello.mode == 1) {
        hello.convertPPTX2Image3(hello.filename);
        System.out.println("Done.");
      }
    }
  }

  /**
   * 输出指令格式及错误信息
   * @param error 错误信息
   */
  private static void usage(String error){
    String msg =
            "Usage: exe [options] --src=<.ppt/.pptx file>\n" +
                    (error == null ? "" : ("Error: "+error+"\n")) +
                    "Options:\n" +
                    "    --dest=<dir>     output directory, defaults to origin of the ppt/pptx file\n" +
                    "    --width=<width>  image width\n" +
                    "    --height=<height> image height\n" +
                    "    --format=<type>    png,gif,jpg\n";
//                    "    --mode=<mode>    0, 1 (0 : use poi api; 1 : use spire.presentation api)";

    System.out.println(msg);
  }

  /**
   * 处理命令行参数
   * @param args 参数数组
   * @return 处理是否成功
   */
  private boolean parseCommandLine(String[] args) {
    if (args.length == 0) {
      usage(null);
      return false;
    }

    for (int i = 0; i < args.length; i++) {
      String opt1 = args[i];
      if (opt1 == null || opt1.indexOf("=") == 0) {
        continue;
      }
      String key = opt1.substring(0, opt1.indexOf("="));
      String val = opt1.substring(opt1.indexOf("=") + 1);
      if (val.trim().length() == 0) {
        continue;
      }
      System.out.println(key + " : " + val);
      switch (key.toLowerCase(Locale.ROOT)) {
        case "--format":
          format = val;
          break;
        case "--dest":
          outdir = new File(val);
          break;
        case "--width":
          try {
            width = Integer.parseInt(val);
          } catch (Exception ex) {

          }
          break;
        case "--height":
          try {
            height = Integer.parseInt(val);
          } catch (Exception ex) {

          }
          break;
        case "--mode":
          try {
            mode = Integer.parseInt(val);
          } catch (Exception ex) {

          }
          break;
        case "--src":
          filename = val;
          break;
        default:
          break;
      }
    }

    File file = new File(filename);
    if (file == null || !file.exists()) {
      usage("File not specified or it doesn't exist");
      return false;
    }

    if (format == null || !format.matches("^(png|gif|jpg)$")) {
      usage("Invalid format given");
      return false;
    }

    if (outdir == null) {
        outdir = new File(filename).getAbsoluteFile().getParentFile();
    }

    //判断输出路径是否存在，如果不存在，则创建；如果创建失败，则输出提示信息并退出。
    if (!outdir.exists()) {
      if (!outdir.mkdir()) {
        usage("Outdir doesn't exist");
        return false;
      }
    }

    if (!"null".equals(format) && (outdir == null || !outdir.exists() || !outdir.isDirectory())) {
      usage("Output directory doesn't exist");
      return false;
    }

    return true;
  }

  private Hello() {
  }

  /**
   * 输入文件名
   */
  private String filename = null;
  /**
   * 输出图片格式
   */
  private String format = "png";
  /**
   * 图片输出目录
   */
  private File outdir = null;
  private int width = 0;
  private int height = 0;
  /**
   * 转换模式
   * 0 - 使用POI工具类
   * 1 - 使用spire.presentation接口
   */
  private int mode = 1;

  /**
   * 使用poi带的工具类PPTX2PNG进行转换
   *
   * Usage: PPTX2PNG [options] <.ppt/.pptx/.emf/.wmf file or 'stdin'>
   *   Options:
   *     -scale <float>    scale factor
   *     -fixSide <side>   specify side (long,short,width,height) to fix - use <scale> as amount of pixels
   *     -slide <integer>  1-based index of a slide to render
   *     -format <type>    png,gif,jpg,svg,pdf (log,null for testing)
   *     -outdir <dir>     output directory, defaults to origin of the ppt/pptx file
   *     -outfile <file>   output filename, defaults to "${basename}-${slideno}.${format}"
   *     -outpat <pattern> output filename pattern, defaults to "${basename}-${slideno}.${format}"
   *                       patterns: basename, slideno, format, ext
   *     -dump <file>      dump the annotated records to a file
   *     -quiet            do not write to console (for normal processing)
   *     -ignoreParse      ignore parsing error and continue with the records read until the error
   *     -extractEmbedded  extract embedded parts
   *     -inputType <type> default input file type (OLE2,WMF,EMF), default is OLE2 = Powerpoint
   *                       some files (usually wmf) don't have a header, i.e. an identifiable file magic
   *     -textAsShapes     text elements are saved as shapes in SVG, necessary for variable spacing
   *                       often found in math formulas
   *     -charset <cs>     sets the default charset to be used, defaults to Windows-1252
   *     -emfHeaderBounds  force the usage of the emf header bounds to calculate the bounding box
   *     -fontdir <dir>    (PDF only) font directories separated by ";" - use $HOME for current users home dir
   *                       defaults to the usual platform directories
   *     -fontTtf <regex>  (PDF only) regex to match the .ttf filenames
   *     -fontMap <map>    ";"-separated list of font mappings <typeface from>:<typeface to>
   */
  private void convertPPTX2Image1(final String filename) {
    try {
      String[] args0 = {
              "-format", this.format,
              "-outdir", this.outdir.getCanonicalPath(),
              "-outpat", "ppt_to_img_${slideno}.${format}",
              "-quiet",
              filename
      };

      PPTX2PNG.main(args0);
    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  /**
   * 使用XSLFSlide.draw将slide渲染给Graphics2D对象后保存为文件
   */
  public static void convertPPTX2Image2(final String filename) throws IOException {
    //creating an empty presentation
    File file=new File(filename);
    XMLSlideShow ppt = new XMLSlideShow(new FileInputStream(file));

    //getting the dimensions and size of the slide
    Dimension pgsize = ppt.getPageSize();
    var slide = ppt.getSlides();
    BufferedImage img = null;
    for (int i = 0; i < slide.size(); i++) {
      img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
      Graphics2D graphics = img.createGraphics();
      //clear the drawing area
      graphics.setPaint(Color.white);
      graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
      //render
      slide.get(i).draw(graphics);

      //creating an image file as output
      FileOutputStream out = new FileOutputStream("out/ppt_image_" + i + ".png");
      javax.imageio.ImageIO.write(img, "png", out);
      ppt.write(out);

      out.close();
    }

    System.out.println("Image successfully created");
  }

  public void convertPPTX2Image3(final String filename) throws Exception {
    //创建Presentation对象
    Presentation ppt = new Presentation();

    //加载示例文档
    ppt.loadFromFile(filename);

    //遍历幻灯片
    for (int i = 0; i < ppt.getSlides().getCount(); i++) {
      //注意：目前用的是免费版本的spire.presentation，只能输出前10页
      if (i > 9) {
        continue;
      }

      BufferedImage image;
      //将幻灯片保存为BufferedImage对象
      if (this.width > 0 && this.height > 0) {
        image = ppt.getSlides().get(i).saveAsImage(this.width, this.height);
      } else {
        image = ppt.getSlides().get(i).saveAsImage();
      }

      //将BufferedImage保存为PNG格式文件
      final String outputted = String.format("ppt_to_img_%04d.%s", i, this.format);
      ImageIO.write(image, this.format, new File(outdir, outputted));

      System.out.println("\t" + outputted + " saved(" + image.getWidth() + ", " + image.getHeight() + ").");
    }
    ppt.dispose();
  }

}
